package com.ccp.dev.form.service;

import com.ccp.dev.core.basic.base.BaseService;
import com.ccp.dev.core.basic.internationalization.LocaleMessageSource;
import com.ccp.dev.core.basic.table.*;
import com.ccp.dev.core.basic.util.ContextUtil;
import com.ccp.dev.core.basic.util.UUIDUtils;
import com.ccp.dev.core.basic.web.query.QueryFilter;
import com.ccp.dev.core.util.*;
import com.ccp.dev.form.consts.FormConstants;
import com.ccp.dev.form.dao.FormFieldDao;
import com.ccp.dev.form.dao.FormTableDao;
import com.ccp.dev.system.model.SysDataSource;
import com.ccp.dev.system.service.SysDataSourceService;
import com.ccp.dev.workflow.dao.IdentityDao;
import com.ccp.dev.form.model.FormField;
import com.ccp.dev.form.model.FormTable;
import com.ccp.dev.workflow.model.Identity;
import com.ccp.dev.form.table.TableMetaFactory;
import com.ccp.dev.form.util.FieldPool;
import com.ccp.dev.form.xml.table.BpmFormTableXml;
import com.ccp.dev.form.xml.table.BpmFormTableXmlList;
import com.ccp.dev.form.xml.util.XmlUtil;
import com.ccp.dev.system.model.SysUser;
import com.ccp.dev.system.service.SysTenantDynamicDataService;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.dom4j.Document;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.*;

/**
 * BPM_FORM_TABLE service类
 *
 * @author zhaowj
 */
@Service
public class FormTableService extends BaseService<FormTable> {

    @Resource
    private FormTableDao formTableDao;

    @Resource
    private FormFieldDao formFieldDao;

    @Resource
    private FormFieldService formFieldService;

    @Resource
    private SysTenantDynamicDataService sysTenantDynamicDataService;

    @Resource
    private IdentityDao identityDao;

    @Resource
    private FormDefService formDefService;

    @Resource
    private SysDataSourceService sysDataSourceService;

    @Resource
    protected LocaleMessageSource localeMessageSource;

    @Value("${mybatis.configuration.database-id}")
    private String dataSourceType;

    /**
     * 查询自定义表列表
     *
     * @param queryFilter 查询条件
     * @return 自定义表列表
     */
    public List<FormTable> queryFormTableList(QueryFilter queryFilter) {
        List<FormTable> list = queryList(queryFilter);
        if (list.size() > 0) {
            for (FormTable formTable : list) {
                if (formTable.getIsMain() == FormTable.IS_MAIN) {
                    List<FormTable> subList = formTableDao.querySubByMainTableId(formTable.getTableId());
                    StringBuilder subBuilder = new StringBuilder();
                    for (FormTable subTable : subList) {
                        subBuilder.append(subTable.getTableName() + StringPool.COMMA);
                    }
                    String subStr = subBuilder.toString();
                    if (StringUtil.isNotEmpty(subStr)) {
                        formTable.setSubStr(subStr.substring(0, subStr.lastIndexOf(StringPool.COMMA)));
                    }
                }
            }
        }
        return list;
    }

    /**
     * 通过mainTableId获得所有子表
     *
     * @param mainTableId 主表id
     * @return 子表集合
     */
    public List<FormTable> querySubByMainTableId(String mainTableId) {
        return formTableDao.querySubByMainTableId(mainTableId);
    }

    /**
     * 删除多个表
     *
     * @param aryTableId 表id数组
     * @return 已经关联表单的表名集合
     */
    public Map<String,List<String>> delByTableId(String[] aryTableId) {
        boolean isTableBindForm = false;
        List<String> bindFormList = new ArrayList<>(16);
        List<String> bindTableList = new ArrayList<>(16);
        for (String tableId : aryTableId) {
            FormTable table = getOneById(tableId);
            String fatherTableId = "";
            //删除的时候 判断是否是子表 ，并且判断子表的父表是否绑定表单
            if (table.getIsMain() == FormTable.IS_NOT_MAIN) {
                fatherTableId = table.getMainTableId();
                isTableBindForm = formDefService.isTableBindForm(fatherTableId);
            }
            //查询表中是否存在数据
            int count = countDataInTable(TableModel.getCustomTableName(table.getTableName()));
            if (isTableBindForm) {
                bindFormList.add(table.getTableName());
            } else if(count > 0){
                bindTableList.add(table.getTableName());
            } else {
                // 表未定义表单且表中无数据，可删除
                delCustomTableById(tableId);
            }
        }
        Map<String,List<String>> map = new HashMap<>();
        map.put("bindFormList",bindFormList);
        map.put("bindTableList",bindTableList);
        return map;
    }

    /**
     * 根据表ID删除表定义。
     *
     * <pre>
     * 1.如果该表是主表，那么先删除其所有的关联的子表。
     * 2.根据表的ID删除表定义。
     * </pre>
     *
     * @param tableId id
     */
    @Transactional(rollbackFor = Exception.class)
    public void delCustomTableById(String tableId) {
        ITableOperator tableOperator = AppUtil.getBean(ITableOperator.class);
        FormTable formTable = this.getOneById(tableId);
        if (BeanUtils.isEmpty(formTable)) {
            return;
        }
        String tableName = formTable.getTableName();
        int count = countDataInTable(TableModel.getCustomTableName(tableName));
        if (formTable.getIsMain() == FormTable.IS_MAIN) {
            List<FormTable> subTableList = formTableDao.querySubByMainTableId(tableId);
            for (FormTable subTable : subTableList) {
                // 删除实体表,如果表中有数据则不删除
                if (count <= 0) {
                    String subTableName = TableModel.getCustomTableName(subTable.getTableName());
                    int subCount = countDataInTable(subTableName);
                    if (subCount <= 0) {
                        tableOperator.dropTable(subTableName);
                        //获取表的ID，根据表ID删除动态数据表数据
                        String tId = subTable.getTableId();
                        sysTenantDynamicDataService.delByDataId(tId);
                        //删除自定义表数据
                        formTableDao.delById(subTable.getTableId());
                        //删除子表字段数据
                        formFieldDao.delByTableId(subTable.getTableId());
                    }
                }

            }
        }
        // 删除实体表，如果表中有数据则不删除。
        if (count <= 0) {
            tableOperator.dropTable(TableModel.getCustomTableName(tableName));
            //删除动态数据表数据
            sysTenantDynamicDataService.delByDataId(tableId);
            //删除自定义表
            formTableDao.delById(tableId);
            //删除字段信息
            formFieldDao.delByTableId(tableId);
        }
    }

    /**
     * 查看某个表里面记录的条数
     *
     * @param tableName 表名
     * @return 表记录的条数
     */
    public int countDataInTable(String tableName) {
        ITableOperator tableOperator = AppUtil.getBean(ITableOperator.class);
        int count = 0;
        //先判断表是否存在
        if (tableOperator.isTableExist(tableName)) {
            count = formTableDao.countDataInTable(tableName);
        }
        return count;
    }

    /**
     * 重置自定义表
     *
     * @param tableId 表id
     */
    @Transactional(rollbackFor = Exception.class)
    public void reset(String tableId) {
        ITableOperator tableOperator = AppUtil.getBean(ITableOperator.class);
        FormTable formTable = getOneById(tableId);
        if (BeanUtils.isEmpty(formTable)) {
            return;
        }
        if (formTable.getIsMain() == FormTable.IS_MAIN) {
            List<FormTable> subTableList = formTableDao.querySubByMainTableId(tableId);
            for (FormTable subTable : subTableList) {
                // 先看表是否存在，删除实体表
                tableOperator.dropTable(TableModel.getCustomTableName(subTable.getTableName()));
                if (subTable.isExtTable()) {
                    continue;
                }
                resetFormTableInfo(subTable);
            }
        }
        // 删除实体表。
        tableOperator.dropTable(TableModel.getCustomTableName(formTable.getTableName()));
        resetFormTableInfo(formTable);
    }

    /**
     * 重置表信息
     *
     * @param formTable FormTable
     */
    @Transactional(rollbackFor = Exception.class)
    public void resetFormTableInfo(FormTable formTable) {
        formTable.setIsPublished(FormTable.NOT_PUBLISH);
        formTable.setPublishedBy(null);
        formTable.setPublishTime(null);
        formTableDao.update(formTable);
        List<FormField> fields = formFieldDao.getFieldsByTableId(formTable.getTableId());
        List<String> delIdList = new ArrayList<>();
        for (FormField field : fields) {
            int isDeleted = field.getIsDeleted() == null ? FormField.IS_DELETE_N : field.getIsDeleted();
            if (FormField.IS_DELETE_Y == isDeleted) {
                delIdList.add(field.getFieldId());
            }
        }
        if (delIdList.size() > 0) {
            String[] delIdArray = delIdList.toArray(new String[delIdList.size()]);
            formFieldDao.delByIdArray(delIdArray);
        }
    }


    /**
     * 判断表名是否存在。
     *
     * @param tableName  表名
     * @param dataSource 数据源别名
     */
    public boolean isTableNameExternalExisted(String tableName, String dataSource) {
        int count = formTableDao.isTableNameExternalExisted(tableName, dataSource);
        return count > 0;
    }

    /**
     * 添加外部表。
     *
     * @param table FormTable实体类
     */
    @Transactional(rollbackFor = Exception.class)
    public void addExt(FormTable table) {
        List<FormField> fields = table.getFieldList();
        String tableId = table.getTableId();
        // 添加表
        table.setIsPublished((short) FormConstants.DEFAULT_INT_ONE);
        table.setIsExternal(FormConstants.DEFAULT_INT_ONE);
        // 设置注释
        if (StringUtil.isEmpty(table.getTableDesc())) {
            table.setTableDesc(table.getTableName());
        }
        // 获取数据源名称。
        String dsAlias = table.getDsAlias();
        if (dsAlias.equals(FormConstants.STR_LOCAL)) {
            table.setDsName(FormConstants.STR_LOCAL_DATASOURCE);
        } else {
            SysDataSource sysDataSource = sysDataSourceService.getByAliasAndId(dsAlias, null);
            table.setDsName(sysDataSource.getName());
        }
        //集成system后添加
        SysUser sysUser = (SysUser) ContextUtil.getCurrentUser();
        table.setCreateBy(sysUser.getUserId());
        table.setCreator(sysUser.getFullName());
        table.setCreateTime(new Date());
        // 设定主键字段的数据类型。
        setKeyDataType(table);
        formTableDao.add(table);
        // 添加字段。
        addFields(tableId, fields, true);
        String tenantId = ContextUtil.getCurrentUserTenantId();
        sysTenantDynamicDataService.addSysTenantDynamicData(tableId, tenantId, FormTable.class);
    }

    /**
     * 设定主键字段类型那个。
     *
     * @param table FormTable
     */
    private void setKeyDataType(FormTable table) {
        String pkField = table.getPkField();
        Short pkDataType = FormTable.PKTYPE_NUMBER;
        List<FormField> fields = table.getFieldList();
        for (FormField field : fields) {
            if (field.getFieldName().equalsIgnoreCase(pkField)) {
                if (field.getFieldType().contains(FormField.DATATYPE_NUMBER)) {
                    pkDataType = FormTable.PKTYPE_NUMBER;
                } else {
                    pkDataType = FormTable.PKTYPE_STRING;
                }
            }
        }
        table.setKeyDataType(pkDataType);
    }

    /**
     * 添加自定义表字段。
     *
     * @param tableId    表id
     * @param fields     字段数组
     * @param isExternal 是否外部表
     */
    @Transactional(rollbackFor = Exception.class)
    public void addFields(String tableId, List<FormField> fields, boolean isExternal) {
        List<FormField> fieldList = convertFields(fields, isExternal);
        //属性集合中是否有租户id
        boolean isNotExistTenantId = this.isNotExistTenantId(fieldList);
        //自定义表生成时，自动添加租户ID数据
        if (isNotExistTenantId) {
            FormTable table = formTableDao.getById(tableId);
            if (table.getIsMain() == FormTable.IS_MAIN) {
                FormField field = generateTenantField(tableId);
                fieldList.add(field);
            }
        }
        for (int i = 0; i < fieldList.size(); i++) {
            FormField field = fieldList.get(i);
            String fieldId = UUIDUtils.getUUIDFor32();
            field.setFieldId(fieldId);
            field.setSn(i);
            field.setTableId(tableId);
            if (null == field.getControlType()) {
                field.setControlType(FormField.HIDDEN);
            }
            formFieldDao.add(field);
        }
    }

    /**
     * 转换字段。增加隐藏字段，并设置字段的主键，数据类型，名称，注释信息。
     *
     * @param fields     List<FormField>
     * @param isExternal 是否外部表
     * @return List<FormField>
     */
    private List<FormField> convertFields(List<FormField> fields, boolean isExternal) {
        List<FormField> list = new ArrayList<>();
        int i = 1;
        for (FormField field : fields) {
            field.setSn(i);
            i++;
            if (StringUtil.isEmpty(field.getFieldDesc())) {
                field.setFieldDesc(field.getFieldName());
            }

            list.add(field);
            if (isExternal) {
                continue;
            }

            if (field.getControlType() == null) {
                field.setControlType(FormField.HIDDEN);
                continue;
            }

            if (isExecutorSelector(field.getControlType()) && field.getIsHidden() == FormField.NO_HIDDEN) {
                FormField fieldHidden = this.addHiddenBpmFormField(field);
                list.add(fieldHidden);
            }
        }
        return list;
    }

    /**
     * 判断控件类型是否选择器
     *
     * @param controlType 控件类型
     * @return boolean
     */
    private static boolean isExecutorSelector(Short controlType) {
        if (BeanUtils.isEmpty(controlType)) {
            return false;
        }
        if (controlType == FieldPool.SELECTOR_USER_SINGLE || controlType == FieldPool.SELECTOR_USER_MULTI || controlType == FieldPool.SELECTOR_ORG_SINGLE
                || controlType == FieldPool.SELECTOR_ORG_MULTI || controlType == FieldPool.SELECTOR_POSITION_SINGLE || controlType == FieldPool.SELECTOR_POSITION_MULTI
                || controlType == FieldPool.SELECTOR_ROLE_SINGLE || controlType == FieldPool.SELECTOR_ROLE_MULTI || controlType == FieldPool.SELECTOR_PROCESS_INSTANCE) {
            return true;
        }
        return false;
    }

    /**
     * 添加选择器ID隐藏字段
     *
     * @param field 字段对象
     * @return 字段对象
     */
    private FormField addHiddenBpmFormField(FormField field) {
        FormField fieldHidden = new FormField();
        BeanCopyUtil.copyBean(field,fieldHidden);
        fieldHidden.setFieldId(UUIDUtils.getUUIDFor32());

        fieldHidden.setFieldName(fieldHidden.getFieldName() + FormField.FIELD_HIDDEN);
        fieldHidden.setFieldDesc(field.getFieldDesc() + FormField.FIELD_HIDDEN);
        fieldHidden.setIsHidden(FormField.HIDDEN);
        short valueFrom = fieldHidden.getValueFrom();
        // 设置人员选择器的ID脚本。
        if (valueFrom == FormField.VALUE_FROM_SCRIPT_HIDDEN || valueFrom == FormField.VALUE_FROM_SCRIPT_SHOW) {
            fieldHidden.setScript(fieldHidden.getScriptID());
        }
        return fieldHidden;
    }

    /**
     * 导出自定义表XML
     *
     * @param tableIds 导出的tableIds数组
     * @param map      map
     * @return String
     */
    @Transactional(rollbackFor = Exception.class)
    public String exportXml(String[] tableIds, Map<String, Boolean> map) throws Exception {
        BpmFormTableXmlList bpmFormTableXmls = new BpmFormTableXmlList();
        List<BpmFormTableXml> list = new ArrayList<>();
        //获取租户ID
        String tenantId = ContextUtil.getCurrentUserTenantId();
        for (int i = 0; i < tableIds.length; i++) {
            FormTable formTable = formTableDao.getById(tableIds[i]);
            BpmFormTableXml bpmFormTableXml = this.exportTable(formTable, map);
            FormTable formTables = bpmFormTableXml.getBpmFormTable();

            formTables.setTenantId(tenantId);
            list.add(bpmFormTableXml);
        }
        bpmFormTableXmls.setBpmFormTableXmlList(list);
        return XmlBeanUtil.marshall(bpmFormTableXmls, BpmFormTableXmlList.class);
    }

    /**
     * 导出表的信息
     *
     * @param formTable FormTable
     * @param map       Map<String, Boolean>
     * @return BpmFormTableXml
     */
    public BpmFormTableXml exportTable(FormTable formTable, Map<String, Boolean> map) {

        map = XmlUtil.getTableDefaultExportMap(map);

        BpmFormTableXml bpmFormTableXml = new BpmFormTableXml();
        // 字段列表
        List<FormField> bpmFormFieldList = new ArrayList<>();
        // 流水号列表
        List<Identity> identityList = new ArrayList<>();
        // 子表
        List<BpmFormTableXml> bpmFormTableXmlList = new ArrayList<>();
        String tableId = formTable.getTableId();
        if (BeanUtils.isNotEmpty(tableId)) {
            List<FormField> formFieldList = new ArrayList<>();
            // 字段
            if (BeanUtils.isNotEmpty(map) && BeanUtils.isNotEmpty(map.get(FormConstants.STR_FORM_FIELD))) {
                formFieldList = formFieldDao.getByTableIdContainHidden(tableId);
                this.exportBpmFormTable(formFieldList, bpmFormFieldList);
            }
            // 流水号
            if (BeanUtils.isNotEmpty(map) && BeanUtils.isNotEmpty(map.get(FormConstants.STR_IDENT))) {
                if (map.get(FormConstants.STR_IDENT)) {
                    this.exportIdentity(formFieldList, identityList);
                }
            }
            // 有子表，递归
            if (BeanUtils.isNotEmpty(map) && BeanUtils.isNotEmpty(map.get(FormConstants.STR_SUB_TABLE))) {
                if (map.get(FormConstants.STR_SUB_TABLE)) {
                    this.exportSubTable(tableId, map, bpmFormTableXmlList);
                }
            }
        }

        bpmFormTableXml.setBpmFormTable(formTable);
        if (BeanUtils.isNotEmpty(bpmFormFieldList)) {
            bpmFormTableXml.setBpmFormFieldList(bpmFormFieldList);
        }
        if (BeanUtils.isNotEmpty(identityList)) {
            bpmFormTableXml.setIdentityList(identityList);
        }
        if (BeanUtils.isNotEmpty(bpmFormTableXmlList)) {
            bpmFormTableXml.setBpmFormTableXmlList(bpmFormTableXmlList);
        }
        return bpmFormTableXml;
    }

    /**
     * 导出字段
     *
     * @param formFieldList    字段list
     * @param bpmFormFieldList 空字段list
     */
    private void exportBpmFormTable(List<FormField> formFieldList, List<FormField> bpmFormFieldList) {
        for (FormField bpmFormField : formFieldList) {
            // 脚本
            bpmFormField.setScript(StringUtil.convertScriptLine(bpmFormField.getScript(), true));
            // 下拉框
            bpmFormField.setOptions(StringUtil.convertLine(bpmFormField.getOptions(), true));
            bpmFormFieldList.add(bpmFormField);
        }
    }

    /**
     * 导出流水号
     *
     * @param formFieldList 字段集合
     * @param identityList  流水号集合
     */
    private void exportIdentity(List<FormField> formFieldList, List<Identity> identityList) {
        for (FormField bpmFormField : formFieldList) {
            // 流水号
            if (StringUtil.isNotEmpty(bpmFormField.getIdentity())) {
                Identity identity = identityDao.getByAlias(bpmFormField.getIdentity());
                identityList.add(identity);
            }
        }
    }

    /**
     * 导出子表
     *
     * @param tableId             tableId
     * @param map                 map
     * @param bpmFormTableXmlList List<BpmFormTableXml>
     */
    private void exportSubTable(String tableId, Map<String, Boolean> map, List<BpmFormTableXml> bpmFormTableXmlList) {
        List<FormTable> subTables = formTableDao.getSubTableByMainTableId(tableId);
        if (BeanUtils.isNotEmpty(subTables)) {
            for (FormTable bpmFormTable : subTables) {
                bpmFormTableXmlList.add(this.exportTable(bpmFormTable, map));
            }
        }
    }

    /**
     * 导入自定义表XML
     *
     * @param inputStream 输入流
     * @param tenantId    租户id
     * @throws Exception 异常
     */
    @Transactional(rollbackFor = Exception.class)
    public void importXml(InputStream inputStream, String tenantId) throws Exception {
        Document doc = Dom4jUtil.loadXml(inputStream);
        Element root = doc.getRootElement();
        // 验证格式是否正确
        XmlUtil.checkXmlFormat(root, FormConstants.STR_BPM, FormConstants.STR_TABLES);

        String xmlStr = root.asXML();
        BpmFormTableXmlList bpmFormTableXmlList = (BpmFormTableXmlList) XmlBeanUtil.unmarshall(xmlStr, BpmFormTableXmlList.class);

        List<BpmFormTableXml> list = bpmFormTableXmlList.getBpmFormTableXmlList();
        Set<Identity> identitySet = new HashSet<>();
        for (BpmFormTableXml bpmFormTableXml : list) {
            FormTable bpmFormTable = bpmFormTableXml.getBpmFormTable();
            bpmFormTable.setTenantId(tenantId);
            bpmFormTableXml.setBpmFormTable(bpmFormTable);
            // 导入表，并解析相关信息
            this.importBpmFormTableXml(bpmFormTableXml, tenantId);
            this.setIdentity(bpmFormTableXml.getIdentityList(), identitySet);
        }
        // 流水号的导入
        this.importIdentity(identitySet);
    }

    /**
     * 设置导入的流水号
     *
     * @param identityList 流水号list集合
     * @param identitySet  流水号set集合
     */
    public void setIdentity(List<Identity> identityList, Set<Identity> identitySet) {
        if (BeanUtils.isNotEmpty(identityList)) {
            for (Identity identity : identityList) {
                identitySet.add(identity);
            }
        }
    }

    /**
     * 导入的流水号
     *
     * @param identitySet 流水号Set
     */
    public void importIdentity(Set<Identity> identitySet) throws Exception {
        if (BeanUtils.isNotEmpty(identitySet)) {
            for (Identity identity : identitySet) {
                this.importIdentity(identity);
            }
        }
    }

    /**
     * 导入流水号时插入Identity
     *
     * @param identity Identity
     */
    private void importIdentity(Identity identity) throws Exception {
        Identity isExist = identityDao.getByAlias(identity.getAlias());
        if (isExist == null) {
            identity.setId(UUIDUtils.getUUIDFor32());
            identity.setCurDate(DateFormatUtil.format(new Date(), StringPool.DATE_FORMAT_DATE));
            identityDao.add(identity);
        } else {
            throw new Exception(FormConstants.STR_IDENTITY + identity.getIdentityName() + FormConstants.STR_IDENTITY_EXIST);
        }
    }

    /**
     * 导入时候生成自定义表
     *
     * @param bpmFormTableXmlOri formTable Xml类
     * @throws Exception 异常
     */
    public Map<String, String> importBpmFormTableXml(BpmFormTableXml bpmFormTableXmlOri, String tenantId) throws Exception {
        int isMain = FormTable.IS_MAIN;
        Map<String, String> map = new HashMap<>();
        BpmFormTableXml bpmFormTableXml = this.convertTableId(bpmFormTableXmlOri, "");
        FormTable bpmFormTable = this.convertBpmFormTableXml(bpmFormTableXml, isMain, map);
        //存储主键
        bpmFormTable.setPkField(FormConstants.STR_ID_CAP);
        FormTable table = formTableDao.getByTableName(bpmFormTable.getTableName());
        FormTable originalTable = new FormTable();
        if (BeanUtils.isNotEmpty(table)) {
            originalTable = this.getTableByIdContainHidden(table.getTableId());
        }
        // 导入的表进行
        this.importBpmFormTable(bpmFormTable, isMain, map, tenantId);

        FormTable destFormTable = this.convertBpmFormTableXml(bpmFormTableXml, isMain, map);

        if (destFormTable.getIsPublished().shortValue() == FormTable.NOT_PUBLISH.shortValue()) {
            return map;
        }
        // 对物理表处理
        this.importGenPhysicsTable(destFormTable, originalTable);
        return map;
    }

    /**
     * 导入生成物理表
     *
     * @param destFormTable 目标表
     * @param originalTable 原始表
     * @throws Exception 异常
     */
    private void importGenPhysicsTable(FormTable destFormTable, FormTable originalTable) throws Exception {
        ITableOperator tableOperator = AppUtil.getBean(ITableOperator.class);
        if (BeanUtils.isEmpty(destFormTable)) {
            return;
        }
        boolean isExists = tableOperator.isTableExist(TableModel.getCustomTableName(destFormTable.getTableName()));
        // 物理表不存在则生
        if (!isExists) {
            this.generateTable(destFormTable);
        } else {
            this.importUpdTable(destFormTable, originalTable);
        }
    }

    /**
     * 导入更新表
     *
     * @param destFormTable 目标表
     * @param orginTable    原始表
     * @throws Exception 异常
     */
    private void importUpdTable(FormTable destFormTable, FormTable orginTable) throws Exception {
        String tableName = TableModel.getCustomTableName(destFormTable.getTableName());
        JdbcTemplate jt = (JdbcTemplate) AppUtil.getBean("jdbcTemplate");
        int rtn = jt.queryForObject("select count(*) from " + tableName, Integer.class);
        if (rtn > 0) {
            // 如果存在数据
            this.importDataTable(destFormTable, orginTable, FormTable.IS_MAIN);
        } else {
            // 删除表
            try {
                dropTable(destFormTable);
            } catch (Exception e) {
                // 存在子表的问题
                FormTable bpmFormTable = this.getTableByIdContainHidden(destFormTable.getTableId());
                this.dropTable(bpmFormTable);
                destFormTable.setSubTableList(bpmFormTable.getSubTableList());
            }
            // 生成表
            this.generateTable(destFormTable);
        }
    }

    /**
     * 导入有数据的表 并生成字段
     *
     * @param destFormTable 现在的表
     * @param orginTable    原来的表
     * @param isMain        是否主表
     * @throws Exception 异常
     */
    private void importDataTable(FormTable destFormTable, FormTable orginTable, int isMain) throws Exception {
        ITableOperator tableOperator = AppUtil.getBean(ITableOperator.class);
        String tableName = destFormTable.getTableName();
        List<FormField> fields = destFormTable.getFieldList();
        if (BeanUtils.isNotEmpty(fields)) {
            fields = convertFields(fields, false);
        }

        // 处理是否存在的字段
        BaseTableMeta meta = TableMetaFactory.getMetaData(null, dataSourceType);
        TableModel tableModel = meta.getTableByName(TableModel.getCustomTableName(tableName));
        if (BeanUtils.isNotEmpty(tableModel) && BeanUtils.isNotEmpty(tableModel.getColumnList())) {

            Set<FormField> fileSet = new HashSet<>();
            for (FormField bpmFormField : fields) {
                boolean isExistFieldName = true;
                for (ColumnModel column : tableModel.getColumnList()) {
                    if (column.getName().equalsIgnoreCase(bpmFormField.getFieldName())) {
                        isExistFieldName = false;
                        break;
                    }
                }
                if (isExistFieldName) {
                    fileSet.add(bpmFormField);
                }
            }

            if (BeanUtils.isNotEmpty(fileSet)) {
                for (FormField bpmFormField : fileSet) {
                    // 设置字段id。
                    ColumnModel columnModel = this.getByField(bpmFormField, 2);
                    tableOperator.addColumn(TableModel.getCustomTableName(tableName), columnModel);
                }
            }

        }

        if (isMain == FormTable.IS_NOT_MAIN) {
            return;
        }
        // 子表的处理
        List<FormTable> subTableList = destFormTable.getSubTableList();
        if (BeanUtils.isEmpty(subTableList)) {
            return;
        }
        // 获取原来子表
        List<FormTable> originTableList = orginTable.getSubTableList();

        Map<String, FormTable> originTableMap = new HashMap<>(16);
        for (FormTable originSubTable : originTableList) {
            originTableMap.put(originSubTable.getTableName().toLowerCase(), originSubTable);
        }

        for (FormTable subTable : subTableList) {
            String subTableName = subTable.getTableName().toLowerCase();
            if (originTableMap.containsKey(subTableName)) {
                // 更新表
                this.importDataTable(destFormTable, orginTable, FormTable.IS_NOT_MAIN);
            }
            // 新加的子表。
            else {
                List<FormField> subFields = subTable.getFieldList();
                subFields = this.convertFields(subFields, false);
                TableModel subTableModel = this.getTableModelByBpmFormTable(subTable);
                tableOperator.createTable(subTableModel);
                tableOperator.addForeignKey(TableModel.getCustomTableName(tableName), TableModel.getCustomTableName(subTable.getTableName()), TableModel.PK_COLUMN_NAME, TableModel.FK_COLUMN_NAME);
            }
        }
    }

    /**
     * 一次性删除表。
     *
     * @param table FormTable
     * @throws SQLException 异常
     */
    public void dropTable(FormTable table){
        ITableOperator tableOperator = AppUtil.getBean(ITableOperator.class);
        for (FormTable subTable : table.getSubTableList()) {
            String subTableName = TableModel.getCustomTableName(subTable.getTableName());
            tableOperator.dropTable(subTableName);
        }
        tableOperator.dropTable(TableModel.getCustomTableName(table.getTableName()));
    }

    /**
     * 根据BpmFormTable一次性生成表。
     * 同时创建主表和子表并创建外键。
     *
     * @param table FormTable
     * @throws SQLException 异常
     */
    private void generateTable(FormTable table) throws SQLException {
        ITableOperator tableOperator = AppUtil.getBean(ITableOperator.class);
        // 创建主表
        TableModel mainTableModel = getTableModelByBpmFormTable(table);
        tableOperator.createTable(mainTableModel);
        for (FormTable subTable : table.getSubTableList()) {
            TableModel subTableModel = getTableModelByBpmFormTable(subTable);
            tableOperator.createTable(subTableModel);
            tableOperator.addForeignKey(TableModel.getCustomTableName(table.getTableName()), TableModel.getCustomTableName(subTable.getTableName()), TableModel.PK_COLUMN_NAME, TableModel.FK_COLUMN_NAME);
        }
    }

    /**
     * 根据BpmFormTable获取TableModel对象。
     *
     * @param table FormTable
     */
    private TableModel getTableModelByBpmFormTable(FormTable table) {
        TableModel tableModel = new TableModel();
        tableModel.setName(TableModel.getCustomTableName(table.getTableName()));
        tableModel.setComment(table.getTableDesc());

        // 给表添加主键
        ColumnModel pkModel = getByField(null, 1);
        tableModel.addColumnModel(pkModel);

        // 添加自定义表的字段。
        for (FormField field : table.getFieldList()) {
            if(FormConstants.STR_ID_CAP.equalsIgnoreCase(StringUtil.trim(field.getFieldName(), " "))){
                continue;
            }
            field.setFieldName(StringUtil.trim(field.getFieldName(), " "));
            ColumnModel columnModel = getByField(field, 2);
            tableModel.addColumnModel(columnModel);
        }
        // 如果表定义为子表的情况。
        // 添加一个外键的列定义。
        if (table.getIsMain() == FormTable.IS_NOT_MAIN) {
            ColumnModel fkModel = getByField(null, 3);
            tableModel.addColumnModel(fkModel);
        }
        return tableModel;
    }

    /**
     * 根据表字段获取列定义对象。 columnType: 1.主键 2.一般列 3.外键 4.用户字段 5.流程RUN字段 6.流程定义ID 7.获取默认时间字段 8.组织字段
     *
     * @param field      FormField
     * @param columnType 字段类型
     * @return ColumnModel
     */
    private ColumnModel getByField(FormField field, int columnType) {
        ColumnModel columnModel = new ColumnModel();
        switch (columnType) {
            // 主键
            case 1:
                columnModel.setName(TableModel.PK_COLUMN_NAME);
                columnModel.setColumnType(ColumnModel.COLUMNTYPE_VARCHAR);
                columnModel.setCharLen(FormConstants.DEFAULT_STR_LENGTH);
                columnModel.setComment(FormConstants.STR_PRIMARY_KEY);
                columnModel.setIsPk(true);
                columnModel.setIsNull(false);
                break;
            // 一般列
            case 2:
                columnModel.setName(field.getFieldName());
                columnModel.setColumnType(field.getFieldType());
                columnModel.setCharLen(field.getCharLen());
                columnModel.setIntLen(field.getIntLen());
                columnModel.setDecimalLen(field.getDecimalLen());
                columnModel.setIsNull(field.getIsRequired() == 0);
                columnModel.setComment(field.getFieldDesc());
                break;
            // 外键
            case 3:
                columnModel.setName(TableModel.FK_COLUMN_NAME);
                columnModel.setColumnType(ColumnModel.COLUMNTYPE_VARCHAR);
                columnModel.setCharLen(FormConstants.DEFAULT_STR_LENGTH);
                columnModel.setComment(FormConstants.STR_FOREIGN_KEY);
                columnModel.setIsFk(true);
                columnModel.setIsNull(false);
                break;
            // 用户字段
            case 4:
                columnModel.setName(TableModel.CUSTOMER_COLUMN_CURRENTUSERID);
                columnModel.setColumnType(ColumnModel.COLUMNTYPE_INT);
                columnModel.setIntLen(FormConstants.INT_TWENTY);
                columnModel.setComment(FormConstants.STR_USER_FIELD);
                columnModel.setIsFk(false);
                columnModel.setIsNull(true);
                break;
            // 流程RUN字段。
            case 5:
                columnModel.setName(TableModel.CUSTOMER_COLUMN_FLOWRUNID);
                columnModel.setColumnType(ColumnModel.COLUMNTYPE_INT);
                columnModel.setIntLen(FormConstants.INT_TWENTY);
                columnModel.setComment(FormConstants.STR_FLOW_FIELD);
                columnModel.setIsFk(false);
                columnModel.setIsNull(true);
                break;
            // 流程定义ID。
            case 6:
                columnModel.setName(TableModel.CUSTOMER_COLUMN_DEFID);
                columnModel.setColumnType(ColumnModel.COLUMNTYPE_INT);
                columnModel.setIntLen(FormConstants.INT_TWENTY);
                columnModel.setComment(FormConstants.STR_FLOW_ID);
                columnModel.setIsFk(false);
                columnModel.setIsNull(true);
                break;
            // 获取默认时间字段
            case 7:
                String defaultValue = getDefaultCurrentTime();
                columnModel.setName(TableModel.CUSTOMER_COLUMN_CREATETIME);
                columnModel.setColumnType(ColumnModel.COLUMNTYPE_DATE);
                columnModel.setComment(FormConstants.STR_INSERT_TIME);
                columnModel.setIsFk(false);
                columnModel.setIsNull(true);
                columnModel.setDefaultValue(defaultValue);
                break;
            // 组织字段
            case 8:
                columnModel.setName(TableModel.CUSTOMER_COLUMN_CURRENTORGID);
                columnModel.setColumnType(ColumnModel.COLUMNTYPE_INT);
                columnModel.setIntLen(FormConstants.INT_TWENTY);
                columnModel.setComment(FormConstants.STR_ORGANIZE_FIELD);
                columnModel.setIsFk(false);
                columnModel.setIsNull(true);
                break;
            default:
                break;
        }
        return columnModel;
    }

    /**
     * 根据数据库获取时间默认值函数用于创建数据库表。
     */
    private String getDefaultCurrentTime() {
        ITableOperator tableOperator = AppUtil.getBean(ITableOperator.class);
        String dbType = tableOperator.getDbType();
        String retStr = "";
        switch (dbType) {
            case SqlTypeConst.ORACLE:
                retStr = "SYSDATE";
                break;
            case SqlTypeConst.MYSQL:
                retStr = "CURRENT_TIMESTAMP";
                break;
            case SqlTypeConst.SQLSERVER:
                retStr = "getdate()";
                break;
            case SqlTypeConst.DB2:
                retStr = "CURRENT DATE";
                break;
            default:
                break;
        }
        return retStr;
    }

    /**
     * 导入表，并解析相关信息
     *
     * @param bpmFormTable FormTable实体类
     * @param map          集合
     * @param isMain       是否主表
     * @param tenantId     租户id
     * @throws Exception 异常
     */
    public void importBpmFormTable(FormTable bpmFormTable, int isMain, Map<String, String> map, String tenantId) throws Exception {
        String tableId = bpmFormTable.getTableId();
        // 导入字段
        List<FormField> bpmFormFieldList = bpmFormTable.getFieldList();
        // 如果存在子表，递归导入子表
        List<FormTable> subTableList = bpmFormTable.getSubTableList();
        // 导入表
        bpmFormTable.setTenantId(tenantId);
        bpmFormTable.setPkField(FormConstants.STR_ID_CAP);
        bpmFormTable = this.importFormTable(bpmFormTable);
        if (BeanUtils.isNotEmpty(bpmFormFieldList)) {
            for (FormField bpmFormField : bpmFormFieldList) {
                this.importFormField(bpmFormField, bpmFormTable);
            }
        }
        map.put(tableId, bpmFormTable.getTableId());
        if (isMain == FormTable.IS_NOT_MAIN) {
            return;
        } else {
            map.put(FormConstants.DEFAULT_STR_ZERO, bpmFormTable.getTableId());
        }

        if (BeanUtils.isNotEmpty(subTableList)) {
            for (FormTable subTable : subTableList) {
                this.importBpmFormTable(subTable, FormTable.IS_NOT_MAIN, map, tenantId);
            }
        }
    }

    /**
     * 导入自定义表时插入 BpmFormTable
     *
     * @param bpmFormTable FormTable实体类
     * @throws Exception 异常
     */
    private FormTable importFormTable(FormTable bpmFormTable) throws Exception {
        FormTable table = formTableDao.getByTableName(bpmFormTable.getTableName());
        String isMain = (bpmFormTable.getIsMain() == FormTable.IS_MAIN) ? FormConstants.STR_ZHU : FormConstants.STR_CONG;
        if (BeanUtils.isEmpty(table)) {
            table = new FormTable();
            String tableId = bpmFormTable.getTableId();
            bpmFormTable.setUpdateTime(new Date());
            BeanUtils.copyNotNullProperties(table, bpmFormTable);
            table.setTableId(tableId);
            formTableDao.add(table);
            String tenantId = bpmFormTable.getTenantId();
            if (StringUtil.isEmpty(tenantId)) {
                tenantId = ContextUtil.getCurrentUserTenantId();
            }
            sysTenantDynamicDataService.addSysTenantDynamicData(tableId, tenantId, FormTable.class);
            return table;
        } else {
            throw new Exception(isMain + FormConstants.STR_TABLE_NAME + bpmFormTable.getTableName() + FormConstants.STR_TABLE_EXIST);
        }

    }

    /**
     * 导入自定义表时插入 BpmFormField
     *
     * @param field        FormField
     * @param bpmFormTable FormTable
     */
    private void importFormField(FormField field, FormTable bpmFormTable) {
        FormField bpmFormField = formFieldDao.getById(field.getFieldId());
        String tableId = bpmFormTable.getTableId();
        if (BeanUtils.isEmpty(bpmFormField)) {
            FormField bpmFormFieldTidFna = formFieldDao.getFieldByTidFna(tableId, field.getFieldName());
            if (BeanUtils.isNotEmpty(bpmFormFieldTidFna)) {
                this.updateTableField(bpmFormFieldTidFna, field, tableId);
            } else {
                field.setTableId(tableId);
                field = this.convertFormField(field);
                formFieldDao.add(field);
            }
        } else {
            this.updateTableField(bpmFormField, field, tableId);
        }
    }

    /**
     * 修改表属性
     *
     * @param bpmFormField FormField
     * @param field        FormField
     * @param tableId      表id
     */
    private void updateTableField(FormField bpmFormField, FormField field, String tableId) {
        String fieldId = bpmFormField.getFieldId();
        field.setUpdateTime(new Date());
        BeanUtils.copyNotNullProperties(bpmFormField, field);
        bpmFormField = this.convertFormField(bpmFormField);
        bpmFormField.setFieldId(fieldId);
        bpmFormField.setTableId(tableId);
        formFieldDao.update(bpmFormField);
    }

    /**
     * 导入自定义表
     *
     * @param field FormField
     */
    private FormField convertFormField(FormField field) {
        field.setFieldId(field.getFieldId());
        // 脚本
        field.setScript(StringUtil.convertScriptLine(field.getScript(), false));
        // 下拉框
        field.setOptions(StringUtil.convertLine(field.getOptions(), false));
        if (isExecutorSelector(field.getControlType())) {
            if (field.getFieldName().lastIndexOf(FormField.FIELD_HIDDEN) != -1) {
                field.setIsHidden(FormField.HIDDEN);
            }
            // 处理导入旧数据
            if (field.getFieldName().lastIndexOf(FormConstants.STR_ID) != -1) {
                field.setIsHidden(FormField.HIDDEN);
                field.setFieldName(field.getFieldName().substring(0, field.getFieldName().length() - 2) + FormField.FIELD_HIDDEN);
            }
        }
        return field;
    }

    /**
     * 查询包含隐藏的表和字段
     *
     * @param tableId tableId
     * @return FormTable
     */
    public FormTable getTableByIdContainHidden(String tableId) {
        FormTable bpmFormTable = formTableDao.getById(tableId);
        if (bpmFormTable == null) {
            return null;
        }
        List<FormField> fieldList = formFieldDao.getByTableIdContainHidden(tableId);
        bpmFormTable.setFieldList(fieldList);
        if (bpmFormTable.getIsMain() == FormTable.IS_NOT_MAIN) {
            return bpmFormTable;
        }
        List<FormTable> subTableList = formTableDao.getSubTableByMainTableId(tableId);
        if (BeanUtils.isEmpty(subTableList)) {
            return bpmFormTable;
        }
        for (FormTable table : subTableList) {
            List<FormField> subFieldList = formFieldDao.getFieldsByTableId(table.getTableId());
            table.setFieldList(subFieldList);
        }
        bpmFormTable.setSubTableList(subTableList);
        return bpmFormTable;
    }

    /**
     * 转换导入数据
     *
     * @param bpmFormTableXml BpmFormTableXml
     * @param isMain          是否主表
     * @param map             map
     * @return FormTable
     */
    public FormTable convertBpmFormTableXml(BpmFormTableXml bpmFormTableXml, int isMain, Map<String, String> map) {
        FormTable mainTable;
        mainTable = bpmFormTableXml.getBpmFormTable();
        if (BeanUtils.isNotEmpty(map)) {
            String tableId = map.get(mainTable.getTableId());
            if (BeanUtils.isNotEmpty(tableId)) {
                mainTable.setTableId(tableId);
            }
        }
        if (BeanUtils.isNotEmpty(bpmFormTableXml.getBpmFormFieldList())) {
            List<FormField> mainFields = bpmFormTableXml.getBpmFormFieldList();
            List<FormField> fieldList = new ArrayList<>();
            for (FormField bpmFormField : mainFields) {
                String tableId = map.get(bpmFormField.getTableId());
                if (BeanUtils.isNotEmpty(tableId)) {
                    bpmFormField.setTableId(tableId);
                }
                if (bpmFormField.getIsDeleted() != null && bpmFormField.getIsDeleted().intValue() != FormConstants.DEFAULT_INT_ONE) {
                    fieldList.add(bpmFormField);
                }

            }
            mainTable.setFieldList(fieldList);
        }
        if (isMain == FormTable.IS_NOT_MAIN) {
            return mainTable;
        }
        List<BpmFormTableXml> subTableXmlList = bpmFormTableXml.getBpmFormTableXmlList();
        if (BeanUtils.isEmpty(subTableXmlList)) {
            return mainTable;
        }
        List<FormTable> subTableList = new ArrayList<>();
        for (BpmFormTableXml subTableXml : subTableXmlList) {
            FormTable subTable = convertBpmFormTableXml(subTableXml, FormTable.IS_NOT_MAIN, map);
            subTable.setIsPublished(mainTable.getIsPublished());
            subTableList.add(subTable);
        }
        mainTable.setSubTableList(subTableList);
        return mainTable;
    }

    /**
     * 转换导入的tableId
     *
     * @param bpmFormTableXml BpmFormTableXml
     * @return BpmFormTableXml
     */
    private BpmFormTableXml convertTableId(BpmFormTableXml bpmFormTableXml, String mainTableId) {

        FormTable formTable = bpmFormTableXml.getBpmFormTable();
        formTable.setTableId(UUIDUtils.getUUIDFor32());
        if (StringUtil.isNotEmpty(mainTableId)) {
            formTable.setMainTableId(mainTableId);
        }

        List<FormField> formFieldList = bpmFormTableXml.getBpmFormFieldList();
        for (FormField formField : formFieldList) {
            formField.setTableId(formTable.getTableId());
            formField.setFieldId(UUIDUtils.getUUIDFor32());
        }

        List<BpmFormTableXml> subTableXmlList = bpmFormTableXml.getBpmFormTableXmlList();
        if (BeanUtils.isEmpty(subTableXmlList)) {
            return bpmFormTableXml;
        }
        List<BpmFormTableXml> subTableList = new ArrayList<>();
        for (BpmFormTableXml formTableXml : subTableXmlList) {
            BpmFormTableXml tableXml = convertTableId(formTableXml, formTable.getTableId());
            subTableList.add(tableXml);
        }
        bpmFormTableXml.setBpmFormTableXmlList(subTableList);
        return bpmFormTableXml;
    }

    /**
     * 根据表id获取表的表和表字段的信息。
     *
     * <pre>
     * 	如果输入的是主表id。
     *  那么将返回主表的信息和字段信息，同时返回子表和字段的信息。
     *  字段数据不包含删除的字段和隐藏的字段。
     * </pre>
     *
     * @param tableId tableId
     * @param need    是否包含隐藏或者删除字段   0为正常字段   1为正常字段加上隐藏字段    2 为正常字段加上逻辑删除字段
     * @return FormTable
     */
    public FormTable getByTableId(String tableId, int need) {
        FormTable bpmFormTable = formTableDao.getById(tableId);
        if (bpmFormTable == null) {
            return null;
        }
        this.getTabInfo(bpmFormTable, need);
        return bpmFormTable;
    }

    /**
     * 根据主表获取整个表的信息包括列。
     *
     * @param bpmFormTable 自定义表
     * @param need         是否包含隐藏或者删除字段 0为正常字段 1为正常字段加上隐藏字段 2 为正常字段加上逻辑删除字段
     */
    private void getTabInfo(FormTable bpmFormTable, int need) {
        String tableId = bpmFormTable.getTableId();
        List<FormField> fieldList;
        if (need == FormField.FIELD_NORMAL_HIDDEN) {
            fieldList = formFieldDao.getByTableIdContainHidden(tableId);
        } else if (need == FormField.FIELD_NORMAL_LOGICDEL) {
            fieldList = formFieldDao.getAllByTableId(tableId);
        } else {
            fieldList = formFieldDao.getByTableId(tableId);
            //获取所有列信息并将createtime字段添加到fieldList中
            List<FormField> allFieldList = formFieldDao.getByTableIdContainHidden(tableId);
            for (FormField field : allFieldList) {
                if (field.getIsHidden() == FormField.HIDDEN && FormConstants.FIELD_CREATE_TIME.equalsIgnoreCase(field.getFieldName())) {
                    fieldList.add(field);
                }
            }
        }

        bpmFormTable.setFieldList(fieldList);
        if (bpmFormTable.getIsMain() == FormTable.IS_NOT_MAIN) {
            return;
        }

        List<FormTable> subTableList = formTableDao.getSubTableByMainTableId(tableId);
        if (BeanUtils.isEmpty(subTableList)) {
            return;
        }

        for (FormTable table : subTableList) {
            List<FormField> subFieldList;
            if (need == FormField.FIELD_NORMAL_HIDDEN) {
                subFieldList = formFieldDao.getByTableIdContainHidden(table.getTableId());
            } else if (need == FormField.FIELD_NORMAL_LOGICDEL) {
                subFieldList = formFieldDao.getAllByTableId(table.getTableId());
            } else {
                subFieldList = formFieldDao.getByTableId(table.getTableId());
            }
            table.setFieldList(subFieldList);
        }
        bpmFormTable.setSubTableList(subTableList);
    }

    /**
     * 根据表名判断是否该表在系统中已经定义。
     *
     * @param tableName 表名
     */
    public boolean isTableNameExisted(String tableName) {
        return formTableDao.isTableNameExisted(tableName) > 0;
    }

    /**
     * 保存复制的表和字段
     *
     * @param json 表对象的json字符串
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveCopy(String json) {
        JSONArray jsonArray = JSONArray.fromObject(json);
        Map<String, String> mainTable = new HashMap<>();
        for (Object object : jsonArray) {
            JSONObject jsonObject = JSONObject.fromObject(object);
            String tableId = (String) jsonObject.get("tableId");
            if (BeanUtils.isEmpty(tableId)) {
                continue;
            }
            String tableName = (String) jsonObject.get("tableName");
            String tableDesc = (String) jsonObject.get("tableDesc");

            FormTable bpmFormTable = formTableDao.getById(tableId);
            List<FormField> fieldList = formFieldDao.getByTableIdContainHidden(bpmFormTable.getTableId());
            //属性集合中是否有租户id
            boolean isNotExistTenantId = this.isNotExistTenantId(fieldList);
            //无租户id 添加tenantId字段
            if (isNotExistTenantId) {
                FormField resource = this.generateTenantField(tableId);
                fieldList.add(resource);
            }

            String newTableId = UUIDUtils.getUUIDFor32();
            mainTable.put(tableId, newTableId);

            bpmFormTable.setTableId(newTableId);
            String mainTableId = bpmFormTable.getMainTableId();
            if (StringUtil.isNotEmpty(mainTableId)) {
                bpmFormTable.setMainTableId(mainTable.get(mainTableId));
            }
            //集成system后添加
            SysUser sysUser = (SysUser) ContextUtil.getCurrentUser();
            bpmFormTable.setCreateBy(sysUser.getUserId());
            bpmFormTable.setCreator(sysUser.getFullName());
            bpmFormTable.setCreateTime(new Date());
            bpmFormTable.setTableName(tableName);
            bpmFormTable.setTableDesc(tableDesc);
            bpmFormTable.setPublishTime(new Date());
            bpmFormTable.setIsPublished(new Short(FormConstants.DEFAULT_STR_ZERO));
            bpmFormTable.setIsExternal(FormConstants.DEFAULT_INT_ZERO);
            bpmFormTable.setDsAlias(FormConstants.STR_LOCAL);
            bpmFormTable.setDsName(FormConstants.STR_LOCAL);
            bpmFormTable.setKeyType(new Short(FormConstants.DEFAULT_STR_ZERO));
            //在自定义表中添加数据
            formTableDao.add(bpmFormTable);
            String tenantId = ContextUtil.getCurrentUserTenantId();
            sysTenantDynamicDataService.addSysTenantDynamicData(newTableId, tenantId, FormTable.class);
            // 保存字段
            this.saveBpmFormField(fieldList, newTableId);
        }
    }

    /**
     * 保存字段
     *
     * @param fieldList List<FormField>
     * @param tableId   tableId
     */
    private void saveBpmFormField(List<FormField> fieldList, String tableId) {
        for (FormField bpmFormField : fieldList) {
            bpmFormField.setFieldId(UUIDUtils.getUUIDFor32());
            bpmFormField.setTableId(tableId);
            formFieldDao.add(bpmFormField);
        }
    }

    /**
     * 通过mainTableId获得所有子表
     *
     * @param mainTableId 主表id
     * @return 子表集合
     */
    public List<FormTable> getSubTableByMainTableId(String mainTableId) {
        return formTableDao.getSubTableByMainTableId(mainTableId);
    }


    /**
     * 增加4个字段 创建人、创建时间、更新人、更新时间
     * 20200513 主表增加密级字段dataPrivacyLevel
     * @param tableId tableId
     * @return List<FormField>
     */
    public List<FormField> addDefaultFields(String tableId) {
        List<FormField> fieldList = new ArrayList<>();
        FormField createBy = fieldInfo(tableId, FormConstants.FIELD_CREATE_PERSON, FormConstants.FIELD_TYPE_VARCHAR, FormConstants.STR_CREATE_PERSON);
        fieldList.add(createBy);
        FormField createTime = fieldInfo(tableId, FormConstants.FIELD_CREATE_TIME, FormConstants.FIELD_TYPE_DATE, FormConstants.STR_CREATE_TIME);
        fieldList.add(createTime);
        FormField updateBy = fieldInfo(tableId, FormConstants.FIELD_UPDATE_PERSON, FormConstants.FIELD_TYPE_VARCHAR, FormConstants.STR_UPDATE_PERSON);
        fieldList.add(updateBy);
        FormField updateTime = fieldInfo(tableId, FormConstants.FIELD_UPDATE_TIME, FormConstants.FIELD_TYPE_DATE, FormConstants.STR_UPDATE_TIME);
        fieldList.add(updateTime);
        //主表增加密级字段dataPrivacyLevel
        FormField dataPrivacyLevel = genDataPrivacyLevelColumn(tableId);
        fieldList.add(dataPrivacyLevel);
        return fieldList;
    }

    /**
     * 增加1个字段 排序
     *
     * @param tableId tableId
     * @return List<FormField>
     */
    public FormField addDefaultSortField(String tableId) {
        FormField sort = fieldInfo(tableId, FormConstants.FIELD_SORT, FormConstants.FIELD_TYPE_NUMBER, FormConstants.STR_SORT);
        return sort;
    }

    /**
     * 组装field字段信息
     *
     * @param tableId   tableId
     * @param fieldName 字段名称
     * @param fieldType 字段类型
     * @return FormField
     */
    private FormField fieldInfo(String tableId, String fieldName, String fieldType, String fieldDesc) {
        FormField field = new FormField();
        field.setFieldId(UUIDUtils.getUUIDFor32());
        field.setTableId(tableId);
        field.setFieldName(fieldName);
        field.setFieldType(fieldType);
        field.setIsRequired(FormField.IS_N);
        field.setIsList(FormField.IS_N);
        field.setIsQuery(FormField.IS_N);
        field.setFieldDesc(fieldDesc);
        // 字符长度，仅针对字符类型
        field.setCharLen(FormConstants.DEFAULT_STR_LENGTH);
        // 整数长度，仅针对数字类型
        field.setIntLen(FormConstants.INT_LENGTH);
        // 小数长度，仅针对数字类型
        field.setDecimalLen(FormConstants.DEFAULT_INT_ZERO);
        field.setIsDeleted(FormField.IS_N);
        field.setSn(FormConstants.DEFAULT_INT_ZERO);
        field.setValueFrom(FormField.IS_N);
        field.setControlType(FormField.IS_N);
        field.setIsHidden(FormField.IS_Y);
        field.setIsFlowVar(FormField.IS_N);
        field.setIsAllowMobile(FormField.IS_N);
        field.setIsWebSign(FormField.IS_N);
        return field;
    }

    /**
     * 20200513组装dataPrivacyLevel密级字段信息
     *
     * @param tableId   tableId
     * @return FormField
     */
    private FormField genDataPrivacyLevelColumn(String tableId) {
        FormField field = new FormField();
        field.setFieldId(UUIDUtils.getUUIDFor32());
        field.setTableId(tableId);
        field.setFieldName(FormConstants.DATA_PRIVACY_LEVEL);
        field.setFieldType(FormConstants.FIELD_TYPE_NUMBER);
        field.setIsRequired(FormField.IS_N);
        field.setIsList(FormField.IS_N);
        field.setIsQuery(FormField.IS_N);
        field.setFieldDesc(FormConstants.STR_DATA_PRIVACY_LEVEL);
        // 字符长度，仅针对字符类型
        field.setCharLen(FormConstants.DEFAULT_INT_ZERO);
        // 整数长度，仅针对数字类型
        field.setIntLen(FormConstants.DEFAULT_INT_ONE);
        // 小数长度，仅针对数字类型
        field.setDecimalLen(FormConstants.DEFAULT_INT_ZERO);
        field.setIsDeleted(FormField.IS_N);
        field.setSn(FormConstants.DEFAULT_INT_ZERO);
        field.setValueFrom(FormField.IS_N);
         //11下拉选项
        field.setControlType(FormConstants.CONTROLTYPE_XL);
        field.setIsHidden(FormField.IS_Y);
        field.setIsFlowVar(FormField.IS_N);
        field.setIsAllowMobile(FormField.IS_N);
        field.setIsWebSign(FormField.IS_N);
        return field;
    }

    /**
     * 添加表数据定义
     *
     * @param table 表对象
     */
    @Transactional(rollbackFor = Exception.class)
    public void addFormTable(FormTable table) {
        List<FormField> fields = table.getFieldList();
        String tableId = table.getTableId();
        // 添加表
        table.setTableId(tableId);
        table.setPkField(FormConstants.STR_ID_CAP);
        table.setDsAlias(FormConstants.STR_LOCAL);
        table.setDsName(FormConstants.STR_LOCAL);
        table.setIsExternal(FormConstants.DEFAULT_INT_ZERO);
        // 设置注释
        if (StringUtil.isEmpty(table.getTableDesc())) {
            table.setTableDesc(table.getTableName());
        }
        //集成system后添加
        SysUser sysUser = (SysUser) ContextUtil.getCurrentUser();
        table.setCreateBy(sysUser.getUserId());
        table.setCreator(sysUser.getFullName());
        table.setCreateTime(new Date());
        table.setKeyDataType(FormTable.PKTYPE_STRING);
        formTableDao.add(table);
        // 添加字段。
        addFields(tableId, fields, false);
        String tenantId = ContextUtil.getCurrentUserTenantId();
        sysTenantDynamicDataService.addSysTenantDynamicData(tableId, tenantId, FormTable.class);
    }

    /**
     * 将表定义进行发布
     *
     * @param tableId  表定义ID
     * @param operator 发布人
     * @throws Exception 异常
     */
    @Transactional(rollbackFor = Exception.class)
    public void generateTable(String tableId, String operator) throws Exception {
        FormTable mainTable = formTableDao.getById(tableId);
        // 将主表设为默认版本
        List<FormField> mainFields = formFieldDao.getAllByTableId(tableId);
        if (mainTable.getIsMain() == FormTable.IS_MAIN) {
            FormField field = generateTenantField(tableId);
            mainFields.add(field);

            //增加4个字段 创建人、创建时间、更新人、更新时间
            //20200513 主表增加密级字段dataPrivacyLevel
            List<FormField> defaultFields = addDefaultFields(tableId);
            mainFields.addAll(defaultFields);
        }else{
            //子表 增加排序字段
            FormField sort = addDefaultSortField(tableId);
            mainFields.add(sort);
        }
        mainFields = convertFields(mainFields, false);
        mainTable.setFieldList(mainFields);
        // oracle,mysql 的ddl动作，在创建表之前有一个commit动作，如果创建表有出错则之前的动作不能回滚
        createTable(mainTable);
        // 将主表设为已发布
        publish(tableId, operator);
        List<FormTable> subTables = formTableDao.getSubTableByMainTableId(tableId);
        for (FormTable subTable : subTables) {
            if(FormTable.NOT_PUBLISH.equals(subTable.getIsPublished())){
                List<FormField> subFields = formFieldDao.getAllByTableId(subTable.getTableId());
                //子表 增加排序字段
                FormField sort = addDefaultSortField(subTable.getTableId());
                subFields.add(sort);
                subFields = convertFields(subFields, false);
                subTable.setFieldList(subFields);
                // 创建子表
                createTable(subTable);
                // 将子表设为已发布
                publish(subTable.getTableId(), operator);
            }
        }
    }

    /**
     * 生成租户字段
     *
     * @param tableId 表ID
     */
    public FormField generateTenantField(String tableId) {
        FormField field = new FormField();
        field.setFieldId(UUIDUtils.getUUIDFor32());
        field.setTableId(tableId);
        field.setFieldName(FormConstants.FIELD_TENANTID);
        //数据类型
        field.setFieldType(FormConstants.FIELD_TYPE_VARCHAR);
        //是否必填
        field.setIsRequired(FormField.IS_Y);
        //是否列显示
        field.setIsList(FormField.IS_N);
        //是否查询显示
        field.setIsQuery(FormField.IS_N);
        //说明
        field.setFieldDesc(FormConstants.STR_TENANT_ID);
        // 字符长度，仅针对字符类型
        field.setCharLen(FormConstants.DEFAULT_STR_LENGTH);
        // 整数长度，仅针对数字类型
        field.setIntLen(FormConstants.DEFAULT_INT_ZERO);
        // 小数长度，仅针对数字类型
        field.setDecimalLen(FormConstants.DEFAULT_INT_ZERO);
        // 是否删除
        field.setIsDeleted(FormField.IS_N);
        // 排列顺序
        field.setSn(FormConstants.DEFAULT_INT_ZERO);
        // 值来源 0-表单 1-脚本
        field.setValueFrom(FormField.IS_N);
        // 控件类型
        field.setControlType(FormField.IS_Y);
        // 是否隐藏域
        field.setIsHidden(FormField.IS_Y);
        // 是否流程变量
        field.setIsFlowVar(FormField.IS_N);
        field.setIsAllowMobile(FormField.IS_N);
        field.setIsWebSign(FormField.IS_N);
        return field;
    }

    /**
     * 生成版本字段
     *
     * @param tableId 表ID
     */
    public FormField generateVersionField(String tableId) {
        FormField resource = new FormField();
        resource.setFieldId(UUIDUtils.getUUIDFor32());
        resource.setTableId(tableId);
        resource.setFieldName(FormConstants.FIELD_TYPE_VERSION);
        //数据类型
        resource.setFieldType(FormConstants.FIELD_TYPE_NUMBER);
        //是否必填
        resource.setIsRequired(FormField.IS_Y);
        //是否列显示
        resource.setIsList(FormField.IS_N);
        //是否查询显示
        resource.setIsQuery(FormField.IS_N);
        //说明
        resource.setFieldDesc(FormConstants.STR_VERSION_CONTROL);
        // 字符长度，仅针对字符类型
        resource.setCharLen(FormConstants.DEFAULT_INT_ZERO);
        // 整数长度，仅针对数字类型
        resource.setIntLen(FormConstants.INT_LENGTH);
        // 小数长度，仅针对数字类型
        resource.setDecimalLen(FormConstants.DEFAULT_INT_ZERO);
        // 是否删除
        resource.setIsDeleted(FormField.IS_N);
        // 排列顺序
        resource.setSn(FormConstants.DEFAULT_INT_ZERO);
        // 值来源 0-表单 1-脚本
        resource.setValueFrom(FormField.IS_N);
        // 控件类型
        resource.setControlType(FieldPool.HIDEDOMAIN);
        // 是否隐藏
        resource.setIsHidden(FormField.IS_N);
        // 是否流程变量
        resource.setIsFlowVar(FormField.IS_N);
        resource.setIsAllowMobile(FormField.IS_N);
        resource.setIsWebSign(FormField.IS_N);
        return resource;
    }

    /**
     * 设置表为发布状态
     *
     * @param tableId  表ID
     * @param operator 发布人
     */
    @Transactional(rollbackFor = Exception.class)
    public void publish(String tableId, String operator) {
        FormTable table = new FormTable();
        table.setTableId(tableId);
        table.setPublishedBy(operator);
        table.setIsPublished((short) FormConstants.DEFAULT_INT_ONE);
        table.setPublishTime(new Date());
        formTableDao.updPublished(table);
    }

    /**
     * 根据表和表字段创建实体表
     *
     * @param table 表对象
     * @throws SQLException sql异常
     */
    @Transactional(rollbackFor = Exception.class)
    public void createTable(FormTable table) throws SQLException {
        ITableOperator tableOperator = AppUtil.getBean(ITableOperator.class);
        TableModel tableModel = getTableModelByBpmFormTable(table);
        // 创建表
        tableOperator.createTable(tableModel);
        // 当前表为子表，添加表关联
        if (table.getIsMain() == FormTable.IS_NOT_MAIN) {
            // 创建索引
            tableOperator.createIndex(TableModel.getCustomTableName(table.getTableName()), TableModel.FK_COLUMN_NAME);
        }
    }

    /**
     * 将隐藏字段的脚本放到对应字段的scriptID属性中。
     *
     * @param list 字段集合
     */
    public void convertFieldScript(List<FormField> list) {
        Map<String, FormField> fieldMap = new HashMap<>();
        for (FormField field : list) {
            fieldMap.put(field.getFieldName(), field);
        }
        for (Iterator<FormField> it = list.iterator(); it.hasNext(); ) {
            FormField field = it.next();
            Short controlType = field.getControlType();
            // 是人员选择器
            boolean isSelector = isExecutorSelector(controlType);
            short valueFrom = field.getValueFrom();
            // 选择器 脚本 隐藏字段。
            if (isSelector
                    && field.getIsHidden() == FormField.HIDDEN
                    && field.getIsDeleted() == FormField.IS_DELETE_N) {
                if (valueFrom == FormField.VALUE_FROM_SCRIPT_SHOW
                        || valueFrom == FormField.VALUE_FROM_SCRIPT_HIDDEN) {
                    String script = field.getScript();
                    String fieldId = field.getFieldName();
                    fieldId = StringUtil.trimSufffix(fieldId,
                            FormField.FIELD_HIDDEN);
                    FormField bpmFormField = fieldMap.get(fieldId);
                    bpmFormField.setScriptID(script);
                }
                // 删除隐藏字段。
                it.remove();
            }
        }
    }

    /**
     * 更新表的设计。
     *
     * @param table FormTable
     * @throws Exception 异常
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateTable(FormTable table) throws Exception {
        ITableOperator tableOperator = AppUtil.getBean(ITableOperator.class);
        List<FormField> fields = table.getFieldList();
        String tableId = table.getTableId();
        String tableName = table.getTableName().trim();
        // 获取表定义。
        FormTable originTable = formTableDao.getById(tableId);
        String mainTableId = tableId;
        int isMain = table.getIsMain();
        if (isMain == FormConstants.DEFAULT_INT_ZERO) {
            mainTableId = table.getMainTableId();
        }
        // 修改之前的字段列表
        List<FormField> originFieldList = formFieldDao.getFieldsByTableId(tableId);
        // 设置注释
        if (StringUtil.isEmpty(table.getTableDesc())) {
            table.setTableDesc(tableName);
        }
        // 该表已经有表单定义了。
        boolean hasFormDef = false;
        if (StringUtil.isNotEmpty(tableId)) {
            hasFormDef = formDefService.isTableBindForm(mainTableId);
        }
        // 该表已经有数据了。
        boolean hasData = false;
        if (StringUtil.isNotEmpty(tableName) && table.getIsExternal() == FormTable.NOT_EXTERNAL) {
            if (table.getIsPublished().equals(FormTable.IS_PUBLISH)) {
                Map map = new HashMap(16);
                map.put("tableName", TableModel.getCustomTableName(tableName));
                hasData = formDefService.isTableHasData(map);
            }
        }
        //已经有表单定义或者表里面有数据 1.不能删除字段;2.可以更新字段;3.可以添加字段。
        if (hasFormDef || hasData) {
            hasFormDefOrDataUpdate(fields, originFieldList, table, tableId, tableName);
        } else {
            // 没有表单定义的情况且表里没有数据。
            // 已发布的情况
            if (table.getIsPublished() == FormConstants.DEFAULT_INT_ONE) {
                // 主表的情况
                if (table.getIsMain() == FormConstants.DEFAULT_INT_ONE) {
                    // 获取所有的字表
                    List<FormTable> tableList = formTableDao.getSubTableByMainTableId(tableId);
                    hasNoneAndIsPublishUpdate(table, originTable, tableId, fields);
                    String pkTableName = TableModel.getCustomTableName(table.getTableName());
                    // 重新添加子表外键
                    for (FormTable subTable : tableList) {
                        String tabName = TableModel.getCustomTableName(subTable.getTableName());
                        tableOperator.addForeignKey(pkTableName, tabName, TableModel.PK_COLUMN_NAME, TableModel.FK_COLUMN_NAME);
                    }
                } else {
                    hasNoneAndIsPublishUpdate(table, originTable, tableId, fields);
                }
            } else {
                // 未发布
                // 直接该表的定义。
                formTableDao.update(table);
                // 删除字段，重新加入字段
                formFieldDao.delByTableId(tableId);
                // 添加字段
                addFields(tableId, fields, false);
            }
        }
    }

    /**
     * 在修改表时 已经有表单定义或者表里面有数据 1.不能删除字段;2.可以更新字段;3.可以添加字段。
     *
     * @param fields          List<FormField>
     * @param originFieldList List<FormField>
     * @param table           FormTable
     * @param tableId         表id
     * @param tableName       表名
     */
    private void hasFormDefOrDataUpdate(List<FormField> fields, List<FormField> originFieldList, FormTable table, String tableId, String tableName) throws Exception {
        ITableOperator tableOperator = AppUtil.getBean(ITableOperator.class);
        if (BeanUtils.isNotEmpty(fields)) {
            fields = convertFields(fields, false);
        }
        Map<String, List<FormField>> resultMap = calculateFields(fields, originFieldList);

        // 处理新增的字段
        List<FormField> addList = resultMap.get(FormConstants.STR_ADD);
        // 更新表
        formTableDao.update(table);
        // 需要更新的字段
        List<FormField> updList = resultMap.get(FormConstants.STR_UPD);
        int i = 0;
        if(BeanUtils.isNotEmpty(updList)){
            i = updList.size();
            for (FormField field : updList) {
                formFieldDao.update(field);
            }
        }
        // 没有增加的列就直接返回。
        if (BeanUtils.isEmpty(addList)) {
            return;
        }
        int k = 0;
        // 添加字段
        for (FormField field : addList) {
            k++;
            field.setFieldId(UUIDUtils.getUUIDFor32());
            field.setTableId(tableId);
            field.setSn(k + i);
            formFieldDao.add(field);
            if(FormConstants.STR_ID_CAP.equalsIgnoreCase(StringUtil.trim(field.getFieldName(), " "))){
                continue;
            }
            ColumnModel columnModel = getByField(field, 2);
            String customTableName = tableName;
            if(table.getIsExternal() == FormTable.NOT_EXTERNAL){
                customTableName = TableModel.getCustomTableName(tableName);
            }
            tableOperator.addColumn(customTableName, columnModel);
        }
    }

    /**
     * 在修改表时 1.没有表单定义的情况2.表里没有数据3.表已发布
     *
     * @param table       FormTable
     * @param originTable LFormTable
     * @param tableId     表id
     * @param fields      List<FormField>
     */
    private void hasNoneAndIsPublishUpdate(FormTable table, FormTable originTable, String tableId, List<FormField> fields) throws Exception {
        ITableOperator tableOperator = AppUtil.getBean(ITableOperator.class);
        // 更新表定义，添加表列的定义。
        formTableDao.update(table);
        // 删除列的定义
        formFieldDao.delByTableId(tableId);
        // 添加表列的定义
        addFields(tableId, fields, false);
        // 删除原来的表
        tableOperator.dropTable(TableModel.getCustomTableName(originTable.getTableName()));
        // 重新创建物理表
        List<FormField> fieldList = convertFields(fields, false);
        table.setFieldList(fieldList);
        createTable(table);
    }

    /**
     * 计算字段，这种情况用于在表字段有变化时获取变化的字段，包括添加的字段和删除的字段。
     *
     * @param fields         List<FormField>
     * @param orginFieldList List<FormField>
     * @return Map<String       ,               List       <       FormField>>
     */
    private Map<String, List<FormField>> calculateFields(List<FormField> fields, List<FormField> orginFieldList) {
        return calculateFields(fields, orginFieldList, true);
    }

    /**
     * 计算字段，这种情况用于在表字段有变化时获取变化的字段，包括添加的字段和删除的字段。
     *
     * <pre>
     * 需要注意的是：
     * 	这种情况在表创建之后才会用到。
     *  更新时：
     *  数据库中已有的字段，字段名，字段类型不能修改。
     *  可以添加字段。
     *  返回值类型：Map&lt;String, List&lt;BpmFormField>>
     *
     *  获取更新的字段：
     *  Mapp&lt;String, Listp&lt;BpmFormField>> paraTypeMap= caculateFields(fields,orginFieldList);
     *
     *  新添加的列：
     *  Listp&lt;BpmFormField> addFields=paraTypeMap.get("add");
     *  更新的列:
     *  Listp&lt;BpmFormField> updFields=paraTypeMap.get("upd");
     *
     *  更新列时将原来的tableid和fieldid放到新列中。
     *
     * </pre>
     *
     * @param fields         List<FormField>
     * @param orginFieldList List<FormField>
     * @param isDelete       boolean
     * @return Map<String       ,               List       <       FormField>>
     */
    private Map<String, List<FormField>> calculateFields(List<FormField> fields, List<FormField> orginFieldList, boolean isDelete) {
        Map<String, FormField> originalMap = new HashMap<>();
        Map<String, FormField> curMap = new HashMap<>();
        Map<String, List<FormField>> resultMap = new HashMap<>();

        for (FormField field : orginFieldList) {
            String fieldName = field.getFieldName().toLowerCase();
            originalMap.put(fieldName, field);
        }
        int i = 1;
        for (FormField field : fields) {
            String fieldName = field.getFieldName().toLowerCase();
            curMap.put(fieldName, field);
            field.setSn(i);
            i++;
        }
        for (FormField field : fields) {
            String fieldName = field.getFieldName().toLowerCase();
            if (originalMap.containsKey(fieldName)) {
                FormField originalField = originalMap.get(fieldName);
                field.setFieldId(originalField.getFieldId());
                field.setTableId(originalField.getTableId());
                addField(FormConstants.STR_UPD, resultMap, field);
            } else {
                addField(FormConstants.STR_ADD, resultMap, field);
            }
        }
        // 如果现有的字段中不包含上次的字段则将字段做删除标记。
        int deleteNum = 0;
        // 是否要做标记删除字段的
        if (isDelete) {
            deleteNum = 1;
        }
        for (FormField field : orginFieldList) {
            String fieldName = field.getFieldName().toLowerCase();
            if (!curMap.containsKey(fieldName)) {
                field.setIsDeleted((short) deleteNum);
                addField(FormConstants.STR_UPD, resultMap, field);
            }
        }
        return resultMap;
    }

    /**
     * 添加字段
     *
     * @param key       key
     * @param resultMap map
     * @param field     字段信息
     */
    private void addField(String key, Map<String, List<FormField>> resultMap, FormField field) {
        List<FormField> list;
        if (resultMap.containsKey(key)) {
            list = resultMap.get(key);
        } else {
            list = new ArrayList<>();
            resultMap.put(key, list);
        }
        list.add(field);
    }

    /**
     * 获取选择器关联的字段
     *
     * @param tableId 表id
     * @return Map<String,FormField[]>
     */
    public Map<String, FormField[]> getExecutorSelectorField(String tableId) {
        Map<String, FormField[]> selectorFieldMap = new HashMap<>(16);
        FormTable bpmFormTable = getTableByIdContainHidden(tableId);
        List<FormField> fields = bpmFormTable.getFieldList();
        Map<String, FormField> fieldsMap = new HashMap<>();
        for (FormField field : fields) {
            fieldsMap.put(field.getFieldName(), field);
        }
        for (FormField field : fields) {
            if (isExecutorSelector(field.getControlType()) && field.getIsHidden() == FormField.NO_HIDDEN) {
                if (fieldsMap.containsKey(field.getFieldName() + FormField.FIELD_HIDDEN)) {
                    FormField[] fds = new FormField[2];
                    fds[0] = field;
                    fds[1] = fieldsMap.get(field.getFieldName() + FormField.FIELD_HIDDEN);
                    selectorFieldMap.put(field.getFieldName(), fds);
                }
            }
        }
        return selectorFieldMap;
    }

    /**
     * 删除表定义，如果有子表定义，将子表定义一并删除。
     *
     * @param formTable 表定义对象
     */
    public void delTable(FormTable formTable) {
        String tableId = formTable.getTableId();
        // 删除子表
        List<FormTable> subTableList = formTable.getSubTableList();
        if (BeanUtils.isNotEmpty(subTableList)) {
            for (FormTable subTable : subTableList) {
                String subTableId = subTable.getTableId();
                formFieldDao.delByTableId(subTableId);
                formTableDao.delById(subTableId);
            }
        }
        formFieldDao.delByTableId(tableId);
        formTableDao.delById(tableId);
    }

    /**
     * 将一些特定的字段设置为隐藏 tenantId,createBy,createTime,updateBy,updateTime
     *
     * @param fieldList List<FormField>
     */
    public void hideField(List<FormField> fieldList) {
        for(FormField bpm: fieldList){
            if (bpm.getFieldName().equalsIgnoreCase(FormConstants.FIELD_TENANTID)) {
                bpm.setIsHidden((short) FormConstants.DEFAULT_INT_ONE);
            }
            if (bpm.getFieldName().equalsIgnoreCase(FormConstants.FIELD_CREATE_PERSON)) {
                bpm.setIsHidden((short) FormConstants.DEFAULT_INT_ONE);
            }
            if (bpm.getFieldName().equalsIgnoreCase(FormConstants.FIELD_CREATE_TIME)) {
                bpm.setIsHidden((short) FormConstants.DEFAULT_INT_ONE);
            }
            if (bpm.getFieldName().equalsIgnoreCase(FormConstants.FIELD_UPDATE_PERSON)) {
                bpm.setIsHidden((short) FormConstants.DEFAULT_INT_ONE);
            }
            if (bpm.getFieldName().equalsIgnoreCase(FormConstants.FIELD_UPDATE_TIME)) {
                bpm.setIsHidden((short) FormConstants.DEFAULT_INT_ONE);
            }
        }
    }

    /**
     * 将表的列表转换为FieldLst。
     *
     * @param tableModel 表模板
     * @return List<FormField>
     */
    public List<FormField> convertFieldList(TableModel tableModel) {
        List<FormField> fieldList = new ArrayList<>();
        List<ColumnModel> colList = tableModel.getColumnList();
        for (ColumnModel model : colList) {
            FormField field = new FormField();
            field.setFieldName(model.getName());
            field.setFieldDesc(model.getComment());
            field.setCharLen(model.getCharLen());
            field.setIntLen(model.getIntLen());
            field.setDecimalLen(model.getDecimalLen());
            field.setFieldType(model.getColumnType());
            short isRequired = (short) (model.getIsNull() ? FormConstants.DEFAULT_INT_ZERO : FormConstants.DEFAULT_INT_ONE);
            field.setIsRequired(isRequired);
            setControlType(field);
            fieldList.add(field);
        }
        return fieldList;
    }

    /**
     * 设置字段的默认控件类型。
     *
     * @param field 表单字段
     */
    private void setControlType(FormField field) {
        String fieldType = field.getFieldType();
        if (StringUtil.isEmpty(fieldType)) {
            field.setFieldType(ColumnModel.COLUMNTYPE_VARCHAR);
            fieldType = ColumnModel.COLUMNTYPE_VARCHAR;
        }
        if (fieldType.equalsIgnoreCase(ColumnModel.COLUMNTYPE_VARCHAR)
                || fieldType.equalsIgnoreCase(ColumnModel.COLUMNTYPE_NUMBER)) {
            field.setControlType(FieldPool.TEXT_INPUT);
        } else if (fieldType.equalsIgnoreCase(ColumnModel.COLUMNTYPE_DATE)) {
            field.setControlType(FieldPool.DATEPICKER);
        } else if (fieldType.equalsIgnoreCase(ColumnModel.COLUMNTYPE_CLOB)) {
            field.setControlType(FieldPool.TEXTAREA);
        }
    }

    /**
     * 根据字段的JSON返回字段列表。
     *
     * @param fieldsJson 属性json字符串
     * @return List<FormField> 集合
     */
    public List<FormField> getByFormFieldJson(String fieldsJson) {
        JSONArray aryJson = JSONArray.fromObject(fieldsJson);
        List<FormField> list = new ArrayList<>();
        for (Object obj : aryJson) {
            JSONObject fieldJObject = (JSONObject) obj;
            String options = "";
            String ctlProperty = "";
            if (fieldJObject.containsKey(FormConstants.STR_OPTIONS)) {
                options = fieldJObject.getString(FormConstants.STR_OPTIONS);
                fieldJObject.remove(FormConstants.STR_OPTIONS);
            }
            if (fieldJObject.containsKey(FormConstants.STR_PROPERTY)) {
                ctlProperty = fieldJObject.getString(FormConstants.STR_PROPERTY);
                fieldJObject.remove(FormConstants.STR_PROPERTY);
            }
            FormField bpmFormField = (FormField) JSONObject.toBean(fieldJObject, FormField.class);
            bpmFormField.setOptions(options);
            bpmFormField.setCtlProperty(ctlProperty);
            bpmFormField.setFieldName(StringUtil.trim(bpmFormField.getFieldName(), " "));
            list.add(bpmFormField);
        }
        return list;
    }

    /**
     * 判断表属性集合中是否有租户id
     *
     * @param fieldList 表属性集合
     * @return boolean
     */
    public boolean isNotExistTenantId(List<FormField> fieldList){
        boolean isNotExistTenantId = true;
        for (FormField field : fieldList) {
            if (field.getFieldName().equalsIgnoreCase(FormConstants.FIELD_TENANTID)) {
                isNotExistTenantId = false;
                break;
            }
        }
        return isNotExistTenantId;
    }

    /**
     * 判断表属性集合中是否有version
     *
     * @param fieldList 表属性集合
     * @return boolean
     */
    public boolean isNotExistVersion(List<FormField> fieldList){
        boolean isNotExistVersion = true;
        for (FormField field : fieldList) {
            if (field.getFieldName().equalsIgnoreCase(FormConstants.FIELD_VERSION)) {
                isNotExistVersion = false;
                break;
            }
        }
        return isNotExistVersion;
    }

    /**
     * 导入xml文件时一些共同的消息提示
     *
     * @param tenantId 租户id
     * @param file MultipartFile 导入的文件
     */
    public void importXmlCommonCheck(String tenantId, MultipartFile file)throws Exception{
        //如果没有租户id
        if (StringUtil.isEmpty(tenantId)) {
            throw new Exception(localeMessageSource.getMessage("formTable.importXml.warnTenant"));
        }
        //如果导入文件为空
        if (file == null) {
            throw new Exception(localeMessageSource.getMessage("formTable.importXml.warnNoFile"));
        }
        //如果文件名格式不对
        String filename = file.getOriginalFilename();
        String suffix = "";
        if (StringUtil.isNotEmpty(filename)) {
            suffix = filename.substring(filename.lastIndexOf(".") + 1);
        }
        if (!(StringPool.XML).equals(suffix)) {
            throw new Exception(localeMessageSource.getMessage("dataSource.importXml.fileTypeWarn"));
        }
    }
    /**
     * 获取表字段及子表数据
     * @param formKey formKey
     * @return JSONObject
     */
    public JSONObject getjson(String formKey){
        String tableId=formDefService.getDefaultVersionByFormKey(formKey).getTableId();
        FormTable formTable = getOneById(tableId);
        List<FormField> formFieldList=formFieldService.getByTableId(tableId);
        formTable.setFieldList(formFieldList);
        JSONObject jsonTable = getByTable(formTable);
        JSONArray children = jsonTable.getJSONArray("children");
        //获取子表列表
        List<FormTable> formTables = getSubTableByMainTableId(tableId);
        if (BeanUtils.isNotEmpty(formTables)) {
            for (FormTable table : formTables) {
                List<FormField> subFormFieldList=formFieldService.getByTableId(table.getTableId());
                table.setFieldList(subFormFieldList);
                JSONObject subTable = getByTable(table);
                children.add(subTable);
            }
        }
        return jsonTable;
    }

    /**
     * 根据表获取JSONObject 对象。
     *
     * @param formTable formTable
     * @return JSONObject
     */
    private JSONObject getByTable(FormTable formTable) {
        int isMain = formTable.getIsMain().intValue();
        JSONObject jsonTable = getJsonObj(formTable.getTableName(),
                formTable.getTableName(), formTable.getTableDesc(), 1,
                isMain, "", formTable.isExtTable());
        JSONArray aryField = new JSONArray();

        List<FormField> mainList = formTable.getFieldList();
        for (FormField field : mainList) {
            JSONObject json = getJsonObj(formTable.getTableName(),
                    field.getFieldName(), field.getFieldDesc(), 0, isMain,
                    field.getFieldType(), formTable.isExtTable());
            aryField.add(json);
        }
        jsonTable.accumulate("children", aryField);

        return jsonTable;
    }

    /**
     * 将数据按指定格式进行存放
     * @param tableName 表名
     * @param name 字段名
     * @param comment 字段注释
     * @param isTable 是否为表
     * @param isMain 是否是主表
     * @param dataType 数据类型
     * @param isExternal 是否外部表
     * @return JSONObject
     */
    private JSONObject getJsonObj(String tableName, String name,
                                  String comment, int isTable, int isMain, String dataType,
                                  boolean isExternal) {
        JSONObject json = new JSONObject();
        json.accumulate("name", name).accumulate("comment", comment)
                .accumulate("tableName", tableName)
                .accumulate("isTable", isTable).accumulate("isMain", isMain)
                .accumulate("isExternal", isExternal ? 1 : 0)
                .accumulate("dataType", dataType);
        return json;
    }
    /**
     * 根据流程定义获取流程表的所有数据。
     *
     * <pre>
     * 1.包括表的元数据。
     * 2.表的列元数据列表。
     * 3.子表数据。
     * 4.子表列的元数据。
     * </pre>
     *
     * @param procDefId 流程定义id
     * @return 表对象
     * @throws Exception
     */
    public FormTable getByProcDefId(String procDefId) {
        List<FormTable> tableList = formTableDao.getByProcDefId(procDefId);
        if (BeanUtils.isEmpty(tableList)) {
            throw new RuntimeException("bpm.contains.no.table");
        }

        if (tableList.size() > 1) {
            throw new RuntimeException("bpm.only.related.one.table");
        }

        FormTable formTable = tableList.get(0);
        getTabInfo(formTable, 1);
        return formTable;
    }
    /**
     * 查询表中加密字段信息
     *
     * @param tableId 表Id
     * @return
     */
    public List<FormField> getEncryptFieldByTableId(String tableId) {
        return formFieldDao.getEncryptFieldByTableId(tableId,FormField.ISENCRYPT);
    }

    public FormTable getByAliasTableName(String dsAlias, String tableName) {
        return formTableDao.getByAliasTableName(dsAlias, tableName);
    }

    public FormTable getByTableName(String tableName) {
        return formTableDao.getByTableName(tableName);
    }

    /**
     * 根据父流程定义id查询表
     * @param procDefId
     * @param parentProcDefId
     * @return
     */
    public FormTable getByProcDefIdAndParent(String procDefId, String parentProcDefId) {
        FormTable formTable = formTableDao.getByProcDefIdAndParent(procDefId, parentProcDefId);
        if (formTable == null) {
            return null;
        }
        getTabInfo(formTable, 1);
        return formTable;
    }

    /**
     * 根据tableId 获取主子表的id和name
     * @param tableId 主表id
     * @return list
     */
    public List<Map<String,String>> getByMainTableId(String tableId){
        List<Map<String,String>> list = new ArrayList<>(16);
        FormTable mainTable = formTableDao.getById(tableId);
        list.add(addTableNameAndId(mainTable));
        List<FormTable> subTableList = formTableDao.getSubTableByMainTableId(tableId);
        for(FormTable subTable : subTableList){
            list.add(addTableNameAndId(subTable));
        }
        return list;
    }

    /**
     * 取出formTable中的id和name字段，存到一个map中返回
     * @param formTable 自定义表
     * @return id和name的字段集合
     */
    private Map<String,String> addTableNameAndId(FormTable formTable){
        Map<String,String> map = new HashMap<>(2);
        map.put("tableId",formTable.getTableId());
        map.put("name",formTable.getTableName());
        return map;
    }

    /**
     * 获取默认的导出的Map
     *
     * @param map
     * @return
     */
    public Map<String, Boolean> getDefaultExportMap(Map<String, Boolean> map) {
        if (BeanUtils.isEmpty(map)) {
            map =new HashMap<String,Boolean>(4);
            //
            map.put(FormConstants.STR_FORM_TABLE, true);
            //字段
            map.put(FormConstants.STR_FORM_FIELD, true);
            //子表
            map.put(FormConstants.STR_SUB_TABLE, true);
            //流水号
            map.put(FormConstants.STR_IDENT, true);
        }
        return map;
    }

    public FormTable getById(String tableId) {
        return formTableDao.getById(tableId);
    }
}